package api

import (
	"net/http"
	"strconv"
	"time"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"

	"schedulingsystem/backend/models"
)

// ScheduleHandler 处理排班相关的API请求
type ScheduleHandler struct {
	DB *gorm.DB
}

// NewScheduleHandler 创建一个新的排班处理器
func NewScheduleHandler(db *gorm.DB) *ScheduleHandler {
	return &ScheduleHandler{DB: db}
}

// GetSchedules 获取所有排班记录
func (h *ScheduleHandler) GetSchedules(c *gin.Context) {
	var schedules []models.Schedule
	result := h.DB.Find(&schedules)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取排班列表失败"})
		return
	}

	c.JSON(http.StatusOK, schedules)
}

// GetSchedule 获取单个排班记录
func (h *ScheduleHandler) GetSchedule(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的排班ID"})
		return
	}

	var schedule models.Schedule
	result := h.DB.First(&schedule, id)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "排班记录不存在"})
		return
	}

	c.JSON(http.StatusOK, schedule)
}

// CreateSchedule 创建新排班记录
func (h *ScheduleHandler) CreateSchedule(c *gin.Context) {
	var schedule models.Schedule
	if err := c.ShouldBindJSON(&schedule); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的排班数据"})
		return
	}

	// 验证员工ID
	var employee models.Employee
	if result := h.DB.First(&employee, schedule.EmployeeID); result.Error != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "员工不存在"})
		return
	}

	// 验证班次ID
	var shift models.Shift
	if result := h.DB.First(&shift, schedule.ShiftID); result.Error != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "班次不存在"})
		return
	}

	// 确保日期有效
	if schedule.Date.IsZero() {
		c.JSON(http.StatusBadRequest, gin.H{"error": "排班日期不能为空"})
		return
	}

	// 设置默认状态
	if schedule.Status == "" {
		schedule.Status = "待确认"
	}

	// 移除同一员工同一天只能有一条排班的限制
	// 允许一个员工同一天有多条班次

	result := h.DB.Create(&schedule)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "创建排班失败"})
		return
	}

	c.JSON(http.StatusCreated, schedule)
}

// UpdateSchedule 更新排班记录
func (h *ScheduleHandler) UpdateSchedule(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的排班ID"})
		return
	}

	var schedule models.Schedule
	result := h.DB.First(&schedule, id)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "排班记录不存在"})
		return
	}

	var updatedSchedule models.Schedule
	if err := c.ShouldBindJSON(&updatedSchedule); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的排班数据"})
		return
	}

	// 验证员工ID
	if updatedSchedule.EmployeeID != 0 {
		var employee models.Employee
		if result := h.DB.First(&employee, updatedSchedule.EmployeeID); result.Error != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "员工不存在"})
			return
		}
		schedule.EmployeeID = updatedSchedule.EmployeeID
	}

	// 验证班次ID
	if updatedSchedule.ShiftID != 0 {
		var shift models.Shift
		if result := h.DB.First(&shift, updatedSchedule.ShiftID); result.Error != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "班次不存在"})
			return
		}
		schedule.ShiftID = updatedSchedule.ShiftID
	}

	// 更新日期
	if !updatedSchedule.Date.IsZero() {
		schedule.Date = updatedSchedule.Date
	}

	// 更新状态
	if updatedSchedule.Status != "" {
		schedule.Status = updatedSchedule.Status
	}

	// 移除同一员工同一天只能有一条排班的限制
	// 允许一个员工同一天有多条班次

	result = h.DB.Save(&schedule)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "更新排班失败"})
		return
	}

	c.JSON(http.StatusOK, schedule)
}

// DeleteSchedule 删除排班记录
func (h *ScheduleHandler) DeleteSchedule(c *gin.Context) {
	id, err := strconv.Atoi(c.Param("id"))
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "无效的排班ID"})
		return
	}

	var schedule models.Schedule
	result := h.DB.First(&schedule, id)
	if result.Error != nil {
		c.JSON(http.StatusNotFound, gin.H{"error": "排班记录不存在"})
		return
	}

	result = h.DB.Delete(&schedule)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "删除排班失败"})
		return
	}

	c.JSON(http.StatusOK, gin.H{"message": "排班已删除"})
}

// ScheduleCalendarItem 日历视图排班项
type ScheduleCalendarItem struct {
	ID           uint      `json:"id"`
	EmployeeID   uint      `json:"employee_id"`
	EmployeeName string    `json:"employee_name"`
	ShiftID      uint      `json:"shift_id"`
	ShiftName    string    `json:"shift_name"`
	Date         time.Time `json:"date"`
	StartTime    time.Time `json:"start_time"`
	EndTime      time.Time `json:"end_time"`
	Status       string    `json:"status"`
	ProductID    uint      `json:"product_id"`
	ProductName  string    `json:"product_name"`
}

// GetSchedulesByDateRange 按日期范围获取排班记录
func (h *ScheduleHandler) GetSchedulesByDateRange(c *gin.Context) {
	// 解析查询参数
	startDateStr := c.Query("start_date")
	endDateStr := c.Query("end_date")
	productIDStr := c.Query("product_id")

	var startDate, endDate time.Time
	var err error

	// 解析开始日期
	if startDateStr != "" {
		startDate, err = time.Parse("2006-01-02", startDateStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "无效的开始日期格式，请使用YYYY-MM-DD"})
			return
		}
	} else {
		// 默认为当前日期
		now := time.Now()
		startDate = time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location())
	}

	// 解析结束日期
	if endDateStr != "" {
		endDate, err = time.Parse("2006-01-02", endDateStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "无效的结束日期格式，请使用YYYY-MM-DD"})
			return
		}
	} else {
		// 默认为开始日期后30天
		endDate = startDate.AddDate(0, 0, 30)
	}

	// 确保结束日期不早于开始日期
	if endDate.Before(startDate) {
		c.JSON(http.StatusBadRequest, gin.H{"error": "结束日期不能早于开始日期"})
		return
	}

	// 解析产品ID（可选）
	var productID uint
	if productIDStr != "" {
		prodID, err := strconv.Atoi(productIDStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "无效的产品ID"})
			return
		}
		productID = uint(prodID)
	}

	// 查询排班记录
	var schedules []models.Schedule
	query := h.DB.Where("date BETWEEN ? AND ?", startDate, endDate)

	// 如果指定了产品ID，则添加产品筛选条件
	if productID > 0 {
		// 通过班次关联查询产品ID
		query = query.Joins("JOIN shifts ON schedules.shift_id = shifts.id").Where("shifts.product_id = ?", productID)
	}

	result := query.Find(&schedules)
	if result.Error != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "获取排班列表失败"})
		return
	}

	// 构建包含详细信息的响应
	var calendarItems []ScheduleCalendarItem
	for _, schedule := range schedules {
		var employee models.Employee
		var shift models.Shift

		// 获取员工信息
		if err := h.DB.First(&employee, schedule.EmployeeID).Error; err != nil {
			continue // 跳过找不到员工的排班
		}

		// 获取班次信息
		if err := h.DB.First(&shift, schedule.ShiftID).Error; err != nil {
			continue // 跳过找不到班次的排班
		}

		// 计算实际开始和结束时间（合并日期和时间）
		startTime := time.Date(
			schedule.Date.Year(), schedule.Date.Month(), schedule.Date.Day(),
			shift.StartTime.Hour(), shift.StartTime.Minute(), shift.StartTime.Second(),
			0, schedule.Date.Location(),
		)

		endTime := time.Date(
			schedule.Date.Year(), schedule.Date.Month(), schedule.Date.Day(),
			shift.EndTime.Hour(), shift.EndTime.Minute(), shift.EndTime.Second(),
			0, schedule.Date.Location(),
		)

		// 处理跨天的情况
		if shift.EndTime.Before(shift.StartTime) {
			endTime = endTime.AddDate(0, 0, 1)
		}

		calendarItems = append(calendarItems, ScheduleCalendarItem{
			ID:           schedule.ID,
			EmployeeID:   employee.ID,
			EmployeeName: employee.Name,
			ShiftID:      shift.ID,
			ShiftName:    shift.Name,
			Date:         schedule.Date,
			StartTime:    startTime,
			EndTime:      endTime,
			Status:       schedule.Status,
			ProductID:    shift.ProductID,
			ProductName:  shift.ProductName,
		})
	}

	c.JSON(http.StatusOK, calendarItems)
}
